# Reflections

Аннотации представляют из себя метки в коде, включаемые в текст программы, и используются для хранения метаданных программного кода, необходимых на разных этапах жизненного цикла программы.
Информация, хранимая в аннотациях, может использоваться соответствующими обработчиками для создания необходимых вспомогательных файлов или для маркировки классов, полей и т.д.

В этом задании вам предстоит поработать с аннотациями для описания полей класса. В упражнении в файле *NotNull.java* уже создана аннотация `@NotNull`. Эта аннотация предупреждает о том, что поле, которое ею помечено, не должно принимать значение `null`. Откройте этот файл и посмотрите, как создается новая аннотация.

## main/java/exercise/Address.java

В файле уже создан класс `Address`, описывающий адрес пользователя.

## Задачи

* Расставьте аннотации для полей класса в соответствии со следующими правилами:

  * Поля класса `country`, `city`, `street`, `houseNumber` не могут иметь значение `null`.
  * Поле `flatNumber` может принимать значение `null`, так как не у каждого адреса может быть номера квартиры.

## main/java/exercise/Validator.java

Просто разместить эту аннотацию в коде недостаточно. Сама по себе она не будет проверять, что значение поля равно `null`. Для этого нужен валидатор.

## Задачи

* Создайте класс `Validator` и публичный статический метод `validate()`. Метод принимает на вход экземпляр класса и проверяет, что свойства, помеченные в классе аннотацией `@NotNull`, не имеют значение `null`. Метод должен вернуть список `List` с названием полей, которые не прошли валидацию (т.е. помечены аннотацией `@NotNull`, но при этом имеют значение `null`). Обратите внимание, что свойства в объекте приватные и для обращения к ним нет селекторов, поэтому вам нужно будет воспользоваться рефлексией.

  ```java
  Address address = new Address(null, "London", "1-st street", "7", "2");
  List<String> notValidFields = Validator.validate(address);
  System.out.println(notValidFields); // => [country]

  Address address2 = new Address("England", null, null, "7", "2");
  List<String> notValidFields2 = Validator.validate(address2);
  System.out.println(notValidFields2); // => [city, street]
  ```

## Самостоятельная работа

В файле *main/java/exercise/MinLength.java* создана аннотация `@MinLength`, которая принимает один параметр — минимальную длину. По умолчанию она равна 3. Эта аннотация отмечает, что строка в значении поля класса имеет длину не меньше указанной. Откройте этот файл и изучите, как создать аннотацию с параметрами.

* В классе `Validator` создайте публичный статический метод `advancedValidate()`, который может работать с двумя аннотациями: `@MinLength` и `@NotNull`. Метод должен возвращать словарь `Map`, в котором ключ — это имя поля, не прошедшего валидацию, а значение — список `List` строк, содержащих сообщение об ошибке.

  ```java
  // Фрагмент определения класса
  class Address {

      @NotNull
      @MinLength(4)
      private String country;

      @NotNull
      private String city;

      @NotNull
      private String street;

      @NotNull
      private String houseNumber;
      private String flatNumber;
  }
  ```

  ```java
  Address address = new Address("USA", "Texas", null, "7", "2");
  Map<String, List<String>> notValidFields = Validator.advancedValidate(address);
  System.out.println(notValidFields); // =>  {country=[length less than 4], street=[can not be null]}
  ```

* Напишите тесты на метод `advancedValidate()`
